From 77b8495bc4e51826afa451914d6a3b0df1b62a24 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 23 Jun 2015 18:11:07 +0200 Subject: [PATCH] x11: Query pointer devices' scroll valuators on toplevel enter events We used to "invalidate" scroll valuators, so the next scroll event could be used as the base for the next scroll deltas. This has the inconvenience that it invariably consumes the first event received after enter and, due to interactions with WM overeager passive button grabs, there's a possibility we don't scroll at all if we receive interleaved "smooth scroll" XI_Motion events and XI_Enter events (Normally triggered by regular scroll wheels in mice). In order to fix this, and at the expense of some sync-call overhead on XI_Enter events (one XIQueryDevice call per slave device), query the current scroll valuator state for all the slaves of the entered pointer, so we do know beforehand the right base values. If new devices are plugged while the pointer is on top of the client, the initialized scroll values will match the valuators'. https://bugzilla.gnome.org/show_bug.cgi?id=750994 https://bugzilla.gnome.org/show_bug.cgi?id=750870 --- gdk/x11/gdkdevice-xi2.c | 39 ++++++++++++++++++++-------------- gdk/x11/gdkdevicemanager-xi2.c | 15 +++++-------- gdk/x11/gdkprivate-x11.h | 2 ++ 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/gdk/x11/gdkdevice-xi2.c b/gdk/x11/gdkdevice-xi2.c index 515840b83a..280eb0d5d2 100644 --- a/gdk/x11/gdkdevice-xi2.c +++ b/gdk/x11/gdkdevice-xi2.c @@ -40,7 +40,6 @@ struct _ScrollValuator { guint n_valuator : 4; guint direction : 4; - guint last_value_valid : 1; gdouble last_value; gdouble increment; }; @@ -819,8 +818,8 @@ _gdk_x11_device_xi2_add_scroll_valuator (GdkX11DeviceXI2 *device, scroll.n_valuator = n_valuator; scroll.direction = direction; - scroll.last_value_valid = FALSE; scroll.increment = increment; + scroll.last_value = 0; g_array_append_val (device->scroll_valuators, scroll); } @@ -851,18 +850,10 @@ _gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device, if (delta_ret) *delta_ret = 0; - if (scroll->last_value_valid) - { - if (delta_ret) - *delta_ret = (valuator_value - scroll->last_value) / scroll->increment; + if (delta_ret) + *delta_ret = (valuator_value - scroll->last_value) / scroll->increment; - scroll->last_value = valuator_value; - } - else - { - scroll->last_value = valuator_value; - scroll->last_value_valid = TRUE; - } + scroll->last_value = valuator_value; return TRUE; } @@ -872,17 +863,33 @@ _gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device, } void -_gdk_device_xi2_reset_scroll_valuators (GdkX11DeviceXI2 *device) +_gdk_device_xi2_revalidate_scroll_valuators (GdkX11DeviceXI2 *device) { - guint i; + GdkDisplay *display; + XIDeviceInfo *info; + gint i, ndevices; + + display = gdk_device_get_display (GDK_DEVICE (device)); + + gdk_x11_display_error_trap_push (display); + info = XIQueryDevice (GDK_DISPLAY_XDISPLAY (display), + device->device_id, &ndevices); + gdk_x11_display_error_trap_pop_ignored (display); + + if (!info) + return; for (i = 0; i < device->scroll_valuators->len; i++) { + XIValuatorClassInfo *valuator; ScrollValuator *scroll; scroll = &g_array_index (device->scroll_valuators, ScrollValuator, i); - scroll->last_value_valid = FALSE; + valuator = (XIValuatorClassInfo *) info->classes[scroll->n_valuator + 1]; + scroll->last_value = valuator->value; } + + XIFreeDeviceInfo (info); } void diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c index e63c35b82b..5d374a2f3e 100644 --- a/gdk/x11/gdkdevicemanager-xi2.c +++ b/gdk/x11/gdkdevicemanager-xi2.c @@ -824,13 +824,11 @@ handle_device_changed (GdkX11DeviceManagerXI2 *device_manager, XIDeviceChangedEvent *ev) { GdkDisplay *display; - GdkDevice *device, *source_device; + GdkDevice *device; display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager)); device = g_hash_table_lookup (device_manager->id_table, GUINT_TO_POINTER (ev->deviceid)); - source_device = g_hash_table_lookup (device_manager->id_table, - GUINT_TO_POINTER (ev->sourceid)); if (device) { @@ -841,9 +839,6 @@ handle_device_changed (GdkX11DeviceManagerXI2 *device_manager, g_signal_emit_by_name (G_OBJECT (device), "changed"); } - - if (source_device) - _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device)); } static GdkCrossingMode @@ -1683,16 +1678,16 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, xev->detail != XINotifyInferior && xev->mode != XINotifyPassiveUngrab && gdk_window_get_window_type (window) == GDK_WINDOW_TOPLEVEL) { - if (gdk_device_get_device_type (source_device) != GDK_DEVICE_TYPE_MASTER) - _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device)); + if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER) + _gdk_device_xi2_revalidate_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device)); else { GList *slaves, *l; - slaves = gdk_device_list_slave_devices (source_device); + slaves = gdk_device_list_slave_devices (device); for (l = slaves; l; l = l->next) - _gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (l->data)); + _gdk_device_xi2_revalidate_scroll_valuators (l->data); g_list_free (slaves); } diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index c2afecf46d..459b76e7d9 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -246,6 +246,8 @@ gboolean _gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device, GdkScrollDirection *direction_ret, gdouble *delta_ret); void _gdk_device_xi2_reset_scroll_valuators (GdkX11DeviceXI2 *device); +void _gdk_device_xi2_revalidate_scroll_valuators (GdkX11DeviceXI2 *device); + gdouble gdk_x11_device_xi2_get_last_axis_value (GdkX11DeviceXI2 *device, gint n_axis); -- 2.30.2